package com.wandousoushu.jiusen.ui.info

import android.app.Application
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import com.wandousoushu.jiusen.MyApplication
import com.wandousoushu.jiusen.R
import com.wandousoushu.jiusen.base.BaseViewModel
import com.wandousoushu.jiusen.booksource.bean.BookChapter
import com.wandousoushu.jiusen.booksource.data.entities.Book
import com.wandousoushu.jiusen.booksource.data.entities.ReadBook
import com.wandousoushu.jiusen.booksource.model.*
import com.wandousoushu.jiusen.help.BookHelp
import kotlinx.coroutines.Dispatchers.IO

class BookInfoViewModel(application: Application) : BaseViewModel(application) {
    val bookData = MutableLiveData<Book>()
    val chapterListData = MutableLiveData<List<BookChapter>>()
    var durChapterIndex = 0
    var inBookshelf = false
    var inBookMark=false

    fun initData(intent: Intent) {
        execute {
            val name = intent.getStringExtra("name") ?: ""
            val author = intent.getStringExtra("author") ?: ""
            BookManager.GetInstance().GetBookMark(name,author)?.let {
                inBookMark=true
            }
            BookManager.GetInstance().GetBookShlef(name,author)?.let { book ->
                inBookshelf = true
                setBook(book)
            } ?: SearchBookManager.GetInstance().getFirstSearchBookByNameAuthor(name, author)?.toBook()?.let { book ->
                setBook(book)
            }
        }
    }

    private fun setBook(book: Book) {
        durChapterIndex = book.durChapterIndex
        bookData.postValue(book)
        if (book.tocUrl.isEmpty()) {
            loadBookInfo(book)
        } else {
//            val chapterList = App.db.bookChapterDao().getChapterList(book.bookUrl)
            val chapterList = BookChapterManager.GetInstance().GetBookChaptersByUrl(book.bookUrl)
            if (chapterList.isNotEmpty()) {
                chapterListData.postValue(chapterList)
            } else {
                loadChapter(book)
            }
        }
    }

    fun upBook(book: Book) {
        durChapterIndex = book.durChapterIndex
        if (book.tocUrl.isEmpty()) {
            loadBookInfo(book)
        } else {
            val chapterList = BookChapterManager.GetInstance().GetBookChaptersByUrl(book.bookUrl)
            if (chapterList.isNotEmpty()) {
                chapterListData.postValue(chapterList)
            } else {
                loadChapter(book)
            }
        }
    }

    fun loadBookInfo(
        book: Book,
        changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null
    ) {
        execute {
            if (book.isLocalBook()) {
                loadChapter(book, changeDruChapterIndex)
            } else {
                //App.db.bookSourceDao().getBookSource(book.origin)
                BookSourceManager.GetInstance().getBookSource(book.origin)?.let { bookSource ->
                    WebBook(bookSource).getBookInfo(book, this)
                        .onSuccess(IO) {
                            bookData.postValue(book)
//                            if (inBookshelf) {
//                                App.db.bookDao().update(book)
//                            }
                            loadChapter(it, changeDruChapterIndex)
                        }.onError {
                            toast(R.string.error_get_book_info)
                        }
                } ?: let {
                    chapterListData.postValue(null)
                    toast(R.string.error_no_source)
                }
            }
        }
    }

    private fun loadChapter(
        book: Book,
        changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null
    ) {
        execute {
            BookSourceManager.GetInstance().getBookSource(book.origin)?.let { bookSource ->
                    WebBook(bookSource).getChapterList(book, this)
                        .onSuccess(IO) {
                            if (it.isNotEmpty()) {
                                if (inBookshelf) {
//                                    App.db.bookDao().update(book)
//                                    App.db.bookChapterDao().insert(*it.toTypedArray())
                                    //MyApplication.instance.AddBookByType(book,2)
                                    BookChapterManager.GetInstance().AddBookChapters(it)
                                }
                                if (changeDruChapterIndex == null) {
                                    chapterListData.postValue(it)
                                } else {
                                    changeDruChapterIndex(it)
                                }
                            } else {
                                toast(R.string.chapter_list_empty)
                            }
                        }.onError {
                            chapterListData.postValue(null)
                            toast(R.string.error_get_chapter_list)
                        }
                } ?: let {
                    chapterListData.postValue(null)
                    toast(R.string.error_no_source)
                }
        }.onError {
//            toast("LoadTocError:${it.localizedMessage}")
        }
    }

    fun loadGroup(groupId: Int, success: ((groupNames: String?) -> Unit)) {
        execute {
//            val groupNames = arrayListOf<String>()
//            App.db.bookGroupDao().all.forEach {
//                if (groupId and it.groupId > 0) {
//                    groupNames.add(it.groupName)
//                }
//            }
//            groupNames.joinToString(",")
        }.onSuccess {
//            success.invoke(it)

        }
    }

    fun changeTo(newBook: Book) {
        execute {
            if (inBookshelf) {
                bookData.value?.changeTo(newBook)
            }
            bookData.postValue(newBook)
            if (newBook.tocUrl.isEmpty()) {
                loadBookInfo(newBook) { upChangeDurChapterIndex(newBook, it) }
            } else {
                loadChapter(newBook) { upChangeDurChapterIndex(newBook, it) }
            }
        }
    }

    private fun upChangeDurChapterIndex(book: Book, chapters: List<BookChapter>) {
        execute {
            book.durChapterIndex = BookHelp.getDurChapterIndexByChapterTitle(
                book.durChapterTitle,
                book.durChapterIndex,
                chapters
            )
            book.durChapterTitle = chapters[book.durChapterIndex].title
            if (inBookshelf) {
//                MyApplication.getInstance().AddBook(book)
//                MyApplication.getInstance().AddBookChapters(chapters)
//                App.db.bookDao().insert(book)
//                App.db.bookChapterDao().insert(*chapters.toTypedArray())
                BookManager.GetInstance().UpdateBook(book)
            }
            bookData.postValue(book)
            chapterListData.postValue(chapters)
        }
    }

    fun saveBook(success: (() -> Unit)? = null) {
        execute {
            bookData.value?.let { book ->
//                if (book.order == 0) {
//                    book.order = BookManager.GetInstance().bookMaxOrder +1;
//                }
                BookManager.GetInstance().GetBookShlef(book.name,book.author)?.let {
                    book.durChapterPos = it.durChapterPos
                    book.durChapterTitle = it.durChapterTitle
                }
                //MyApplication.instance.AddBookByType(book,2)
                if (ReadBook.book?.name == book.name && ReadBook.book?.author == book.author) {
                    ReadBook.book = book
                }
            }
        }.onSuccess {
            success?.invoke()
        }
    }

    fun saveChapterList(success: (() -> Unit)?) {
        execute {
            chapterListData.value?.let {
                //App.db.bookChapterDao().insert(*it.toTypedArray())
                BookChapterManager.GetInstance().AddBookChapters(it)
            }
        }.onSuccess {
            success?.invoke()
        }
    }

    fun addToBookshelf(success: (() -> Unit)?) {
        execute {
            bookData.value?.let { book ->
//                if (book.order == 0) {
//                    book.order=MyApplication.instance.bookMaxOrder +1;
//                    //book.order = App.db.bookDao().maxOrder + 1
//                }
                //App.db.bookDao().getBook(book.name, book.author)
                BookManager.GetInstance().GetBookShlef(book.name,book.author)?.let {
                    book.durChapterPos = it.durChapterPos
                    book.durChapterTitle = it.durChapterTitle
                }
                BookManager.GetInstance().AddBooktoShelf(book,2)
                //App.db.bookDao().insert(book)
            }
            chapterListData.value?.let {
                BookChapterManager.GetInstance().AddBookChapters(it)
                //App.db.bookChapterDao().insert(*it.toTypedArray())
            }
            inBookshelf = true
        }.onSuccess {
            success?.invoke()
        }
    }

    fun addToBookmark(success: (() -> Unit)?) {
        execute {
            bookData.value?.let { book ->
                BookManager.GetInstance().AddBooktoMark(book,1)
            }
            inBookMark=true
        }.onSuccess {
            success?.invoke()
        }
    }

    fun delBookShlef(deleteOriginal: Boolean = false, success: (() -> Unit)? = null) {
        execute {
            bookData.value?.let {
                it.deleteShelf()
                inBookshelf = false
//                if (it.isLocalBook()) {
//                    LocalBook.deleteBook(it, deleteOriginal)
//                }
            }
        }.onSuccess {
            success?.invoke()
        }
    }

    fun delBookMark(deleteOriginal: Boolean = false, success: (() -> Unit)? = null) {
        execute {
            bookData.value?.let {
                it.deleteMark()
                inBookMark = false
//                if (it.isLocalBook()) {
//                    LocalBook.deleteBook(it, deleteOriginal)
//                }
            }
        }.onSuccess {
            success?.invoke()
        }
    }

//    fun upEditBook() {
//        bookData.value?.let {
//            MyApplication.instance.getSearchBookByUrl(it.bookUrl)?.let { book ->
//                bookData.postValue(book)
//            }
//        }
//    }
}